12.4.2 デッドロックの回避
デッドロック(互いに相手を待つことにより前に進めない)の例として下記のような場合がある
一方がチャネルch1から送信しようとし、もう一方がチャネルch2から受信しようとしている
どちらも同じチャネルから送信しようとしている、あるいは同じチャネルから受信しようとしている
受信先が見つからない場合
code:go
package main
import (
"fmt"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
ch1 <- "ゴルーチンから送信した文字列" // ch1に書き込めない限りここで待たされる
v1 := <-ch2
fmt.Println(v1)
}()
ch2 <- "mainから送信した文字列" // ch2に書き込めない限りここで待たされる
v2 := <-ch1
fmt.Println(v2)
}
デッドロックになるとGoのランタイムがプログラムを強制終了する
fatal error: all goroutines are asleep - deadlock!
こうした場合にselect文を使用するとデッドロックを回避できる
code:go
package main
import "fmt"
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
ch1 <- "ゴルーチンから送信した文字列"
fromMain := <-ch2
fmt.Println("無名関数:", fromMain)
}()
var fromGoroutine string
select { // チャネルでのやり取りをselectで囲む
case ch2 <- "mainから送信した文字列": // こちらは最初は書き込めない
case fromGoroutine = <-ch1: // ch1に書き込まれればこれが実行される
}
fmt.Println("main:", fromGoroutine)
}